package com.lbw.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lbw.config.Comment;
import com.lbw.entity.*;
import com.lbw.mapper.QuestionEntityMapper;
import com.lbw.mapper.TestEntityMapper;
import com.lbw.mapper.TestQuestionMapper;
import com.lbw.mapper.WrongEntityMapper;
import com.lbw.service.*;
import com.lbw.vo.TestQuestionVo;
import com.lbw.vo.TestScoreVo;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lbw
 * @since 2020-09-13
 */
@Service
public class TestEntityServiceImpl extends ServiceImpl<TestEntityMapper, TestEntity> implements TestEntityService {

    @Resource
    private TestEntityMapper testEntityMapper;

    @Resource
    private TestEntityService testEntityService;

    @Autowired
    private QuestionEntityService questionEntityService;
    @Resource
    private QuestionEntityMapper questionEntityMapper;

    @Resource
    private WrongEntityMapper wrongEntityMapper;

    @Resource
    private TestQuestionMapper testQuestionMapper;

    @Resource
    private TestQuestionService testQuestionService;

    @Autowired
    private WrongEntityService wrongEntityService;
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private ScoreEntityService scoreEntityService;

    /**
     * 抽取在线测试题目，不分单元
     *
     * @param testNum          测试编号
     * @param questionTableNum 题目表
     * @param subjectId        科目编号
     */
/*
    @Override
    public TestEntity selectOnlineTest(String testNum, String questionTableNum, String subjectId) {
        Map<String, String> hashMap = new HashMap<>();
        hashMap.put("testNum", testNum);
        hashMap.put("subjectId", subjectId);
        String questionTable = "";
        TestEntity testEntity = null;
        if ("1".equals(questionTableNum)) {
            //题目测试
            questionTable = Comment.QUESTION_ENTITY;
            hashMap.put("questionTable", questionTable);
            testEntity = testEntityMapper.selectOnlineQuestionTest(hashMap);
        } else if ("2".equals(questionTableNum)) {
            //错题测试
            questionTable = Comment.WRONG_ENTITY;
            hashMap.put("questionTable", questionTable);
            testEntity = testEntityMapper.selectOnlineWrongTest(hashMap);
        }

        //处理答案格式
        return answerFormat(testEntity);
    }
*/

    /**
     * 抽取在线测试题目，按章节测试
     *
     * @param testNum          测试编号
     * @param questionTableNum 题目表
     * @param type        科目编号
     * @param chapterId        章节编号
     */
    @Override
    public TestEntity selectOnlineTestChapter(String testNum, String questionTableNum, Integer type, String chapterId) {
        Map<String, Object> hashMap = new HashMap<>();
        hashMap.put("testNum", testNum);
        hashMap.put("type", type);
        hashMap.put("chapterId", chapterId);
        String questionTable = "";
        TestEntity testEntity = null;
        if ("1".equals(questionTableNum)) {
            questionTable = Comment.QUESTION_ENTITY;
            hashMap.put("questionTable", questionTable);
            testEntity = testEntityMapper.selectOnlineQuestionTest(hashMap);
        } else if ("2".equals(questionTableNum)) {
            questionTable = Comment.WRONG_ENTITY;
            hashMap.put("questionTable", questionTable);
            testEntity = testEntityMapper.selectOnlineWrongTest(hashMap);
        }

        //处理答案格式
        return answerFormat(testEntity);
    }

    /**
     * 处理答案输出格式
     */
    private TestEntity answerFormat(TestEntity testEntity) {
        if (testEntity != null) {
            List<QuestionEntity> entityQuestionEntityList = testEntity.getQuestionEntityList();
            if (entityQuestionEntityList != null && !entityQuestionEntityList.isEmpty()) {
                for (QuestionEntity questionEntity : entityQuestionEntityList) {
                    if (questionEntity.getType() == 1) {
                        //类型为1行测时才进行转换答案格式
                        ArrayList<Map<String, String>> optionsList = new ArrayList<>();

                        String answerOptions = questionEntity.getAnswerOptions();
                        if (answerOptions != null) {
                            String[] split = StringUtils.split(answerOptions, "-");
                            for (String answer : split) {
                                Map<String, String> stringHashMap = new HashMap<>();
                                String[] split1 = StringUtils.split(answer, "、");
                                stringHashMap.put("content", split1[1]);
                                stringHashMap.put("id", split1[0]);
                                optionsList.add(stringHashMap);
                            }

                        }

                        questionEntity.setOptionsList(optionsList);
                    }

                }
            }
        }
        return testEntity;
    }

    /**
     * 抽取在线测试题目，按章节测试
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean extractOnlineTestChapter(TestQuestionVo testQuestionVo) {
        String testNumber = UUID.randomUUID().toString().replaceAll("-", "");
        //判断是否已经存在测试
/*        LambdaQueryWrapper<TestEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //判断是否存在该测试
        lambdaQueryWrapper.eq(TestEntity::getQuestionTable, "1".equals(testQuestionVo.getQuestionTableNum()) ? Comment.QUESTION_ENTITY : Comment.WRONG_ENTITY)
                //.eq(TestEntity::getTestNumber,testQuestionVo.getTestNumber())
                .eq(testQuestionVo.getType() != null, TestEntity::getType, testQuestionVo.getType())
                .eq(StringUtils.isNotBlank(testQuestionVo.getChapterId()), TestEntity::getChapterId, testQuestionVo.getChapterId());
        int count = this.count(lambdaQueryWrapper);
        if (count != 0) {
            //已经存在测试，不需再次添加测试
            return false;
        }*/
        List<TestQuestion> list = new ArrayList<>();
        String questionTable = Comment.QUESTION_ENTITY;
        if ("1".equals(testQuestionVo.getQuestionTableNum())) {
            questionTable = Comment.QUESTION_ENTITY;

            //随机获取题目id，通过科目编号和章节编号随机抽取题目
            QueryWrapper<QuestionEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("id").eq(testQuestionVo.getType() != null, "type", testQuestionVo.getType())
                    .eq(StringUtils.isNotEmpty(testQuestionVo.getChapterId()), "chapter", testQuestionVo.getChapterId())
                    .orderByAsc("RAND()")
                    .last("LIMIT 20");
            List<QuestionEntity> questionEntityList = questionEntityMapper.selectList(queryWrapper);

            //插入到测试表中
            for (QuestionEntity questionEntity : questionEntityList) {
                TestQuestion testQuestion = new TestQuestion();
                testQuestion.setQuestionId(questionEntity.getId());
                testQuestion.setTestNumber(testNumber);
                list.add(testQuestion);
            }
        } else if ("2".equals(testQuestionVo.getQuestionTableNum())) {
            questionTable = Comment.WRONG_ENTITY;
            List<String> wrongIdList = wrongEntityMapper.extractOnlineTestChapter(testQuestionVo.getType(), testQuestionVo.getChapterId());
            for (String wrongId : wrongIdList) {
                TestQuestion testQuestion = new TestQuestion();
                testQuestion.setQuestionId(wrongId);
                testQuestion.setTestNumber(testNumber);
                list.add(testQuestion);
            }

        }

        boolean batch = testQuestionService.saveBatch(list);
        if (batch) {

            //测试表插入数据
            TestEntity testEntity = new TestEntity();
            testEntity.setTestNumber(testNumber);
            testEntity.setQuestionTable(questionTable);
            testEntity.setTestClass(testQuestionVo.getTestClass());
            testEntity.setTestTitle(testQuestionVo.getTestTitle());
            testEntity.setType(testQuestionVo.getType());
            testEntity.setChapterId(testQuestionVo.getChapterId());
            int insert = testEntityMapper.insert(testEntity);
            return insert == 1;
        }
        return false;
    }

    /**
     * 查询测试列表
     *
     * @param type 科目id
     * @param chapterId 章节id
     * @return
     */
    @Override
    public List<TestEntity> showTestList(Integer type, String chapterId) {
        LambdaQueryWrapper<TestEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(type != null, TestEntity::getType, type)
                .eq(StringUtils.isNotBlank(chapterId), TestEntity::getChapterId, chapterId);

        return this.list(lambdaQueryWrapper);
    }

    /**
     * 统计测试分数以及测试错题，及错误答案
     */
    @Override
    public boolean countTestScore(TestScoreVo testScoreVo) {
        //通过测试id修改总份数
        //获取当前测试对象
        /*TestEntity byIdEntity = this.getById(testScoreVo.getTestId());
        byIdEntity.setTotalScore(testScoreVo.getTotalScore());
        boolean update = this.updateById(byIdEntity);
        if (!update) {
            return false;
        }*/
        //答案错误,插入到错题库
        /*LambdaQueryWrapper<WrongEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(WrongEntity::getStuId,testScoreVo.getStuId())
                .in(WrongEntity::getQuestionId,testScoreVo.getQuestionId());
        List<WrongEntity> wrongEntityList = wrongEntityService.list(lambdaQueryWrapper);
        if (wrongEntityList != null && !wrongEntityList.isEmpty()) {

        }*/
/*        LinkedList<WrongEntity> wrongEntityLinkedList = new LinkedList<>();
        List<String> questionIds = testScoreVo.getQuestionId();
        for (String questionId : questionIds) {
            WrongEntity wrongEntity = new WrongEntity();
            wrongEntity.setQuestionId(questionId);
            wrongEntity.setStuId(testScoreVo.getStuId());
            wrongEntityLinkedList.add(wrongEntity);
        }
        //批量新增或修改错题库
        boolean saveOrUpdateBatch = wrongEntityService.saveOrUpdateBatch(wrongEntityLinkedList);

        if (!saveOrUpdateBatch) {
            return false;
        }*/
        //新增到成绩表中
        ScoreEntity scoreEntity = new ScoreEntity();
        scoreEntity.setScore(testScoreVo.getTotalScore().toString());
        scoreEntity.setStuId(testScoreVo.getStuId());
        scoreEntity.setEvaluationId(testScoreVo.getTestId());
        return scoreEntityService.save(scoreEntity);
    }

    /**
     * 如果为申论题目则从es中查询是否正确，返回给前端
     */
    @Override
    public QuestionEntity countCommentQuestion(String questionId, String myAnswer, Integer type, String stuId) throws IOException {
        //先查询出错题库中是否存在该错题
        LambdaQueryWrapper<WrongEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(WrongEntity::getStuId, stuId)
                .eq(WrongEntity::getQuestionId, questionId);
        WrongEntity wrongEntity = wrongEntityService.getOne(lambdaQueryWrapper);
        //通过问题id查询出问题
        QuestionEntity questionEntity = questionEntityService.getById(questionId);
        if (type == 1) {
            //题目为行测
            if (myAnswer.equals(questionEntity.getRightAnswer())) {
                //答案正确
                //设置得分
                questionEntity.setCommentScore(questionEntity.getScore());
                if (wrongEntity != null) {
                    //答案正确但错题库中存在则删除该错题
                    wrongEntityService.removeById(wrongEntity.getId());
                }
            } else {
                //答案错误,插入到错题库
                /*LambdaQueryWrapper<WrongEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(WrongEntity::getStuId, stuId)
                        .eq(WrongEntity::getQuestionId, questionId);
                WrongEntity wrongEntity = wrongEntityService.getOne(lambdaQueryWrapper);*/
                if (wrongEntity == null) {
                    wrongEntity = new WrongEntity();
                    wrongEntity.setQuestionId(questionId);
                    wrongEntity.setStuId(stuId);
                }
                wrongEntity.setLastWrongAnswer(myAnswer);
                wrongEntityService.saveOrUpdate(wrongEntity);
                //设置得分
                questionEntity.setCommentScore(0);
            }
        } else {
            //题目为申论

            //进行es的查询
            SearchResponse searchResponse = esSearch(myAnswer);
            SearchHit[] searchHits = searchResponse.getHits().getHits();
            for (SearchHit searchHit : searchHits) {

                //获取查询结果
                Map<String, Object> sourceAsMapResult = searchHit.getSourceAsMap();
                if (questionId.equals(sourceAsMapResult.get("id"))) {
                    //获取自己答案匹配出的数值
                    float hitScore = searchHit.getScore();
                    //如果查询出数据id与题目id相同，则获取正确答案
                    String rightAnswer = sourceAsMapResult.get("rightAnswer").toString();
                    //进行es的查询,进行正确答案的匹配
                    SearchResponse searchResponseRight = esSearch(rightAnswer);
                    for (SearchHit hitRight : searchResponseRight.getHits().getHits()) {
                        if (questionId.equals(hitRight.getSourceAsMap().get("id"))) {
                            //获取正确答案的匹配数值
                            float hitRightScore = hitRight.getScore();
                            //进行得算分
                            float scoreRate = hitScore / hitRightScore;
                            float score = Float.parseFloat(sourceAsMapResult.get("score").toString());
                            float myScore = scoreRate * score;
                            //分数低于60%则视作错题
                            if (myScore < questionEntity.getScore() * 0.6) {
                                //答案错误,插入到错题库
                                /*LambdaQueryWrapper<WrongEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                                lambdaQueryWrapper.eq(WrongEntity::getStuId, stuId)
                                        .eq(WrongEntity::getQuestionId, questionId);
                                WrongEntity wrongEntity = wrongEntityService.getOne(lambdaQueryWrapper);*/
                                if (wrongEntity == null) {
                                    wrongEntity = new WrongEntity();
                                    wrongEntity.setQuestionId(questionId);
                                    wrongEntity.setStuId(stuId);
                                }
                                wrongEntity.setLastWrongAnswer(myAnswer);
                                wrongEntityService.saveOrUpdate(wrongEntity);
                            }else {
                                if (wrongEntity != null) {
                                    //答案正确但错题库中存在则删除该错题
                                    wrongEntityService.removeById(wrongEntity.getId());
                                }
                            }

                            //设置申论得分
                            questionEntity.setCommentScore(new Float(myScore).intValue());
                            break;
                        }
                    }
                    break;
                }

            }
        }
        return questionEntity;

    }

    /**
     * 在es中进行搜索查询
     *
     * @param answer
     * @return
     * @throws IOException
     */
    private SearchResponse esSearch(String answer) throws IOException {
        //查询请求
        SearchRequest searchRequest = new SearchRequest(Comment.ES_INDEX);
        //搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //条件查询
        //全查询
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("rightAnswer", answer);
        searchSourceBuilder.query(matchQuery);
        //执行搜索
        searchRequest.source(searchSourceBuilder);
        return restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    }

}
